from django.contrib.auth.models import User, Group
from ability.models import *
from rest_framework import serializers
from ability.enums import *
from ability.format import *
from django.conf import settings
from ability.validators import *
from ability.cloud import *
from datetime import datetime
from django.db.models import Avg
from django.db import transaction
import time
import logging

from study.proxmox_utils import proxmox

logger = logging.getLogger(__name__)
from ability.cloud import instStatus

import markdown

from rest_framework.serializers import Serializer

class UserListSerializer(serializers.HyperlinkedModelSerializer):
    class Meta:
        model = UserProfile
        fields = ['id', 'username', 'email', 'user_type']
    
class UserProfileSerializer(serializers.ModelSerializer):

    college_name = serializers.CharField(source='student.belong_class.major.college.college_name', allow_blank=True, default='')
    school_name = serializers.CharField(source='student.belong_class.major.college.school.school_name', allow_blank=True, default='')

    class Meta:
        model = UserProfile
        fields = ['id', 'phone', 'sex', 'real_name', 'email', 'user_type', 'school_name', 'college_name']

class TeacherListSerializer(serializers.HyperlinkedModelSerializer):
    college_name = serializers.CharField(source='college.college_name', allow_blank=True, default='')
    school_name = serializers.CharField(source='college.school.school_name', allow_blank=True, default='')
    username = serializers.CharField(source='user.real_name')
    userid = serializers.CharField(source='user.id')
    phone = serializers.CharField(source='user.phone')
    identity = FormatTransField(source='teacher_type', transname='teacher_identity')
    status = FormatTransField(source='user.user_status', transname='status')
    create_time = serializers.DateTimeField(format="%Y-%m-%d %H:%M:%S", source='user.create_time')
    
    class Meta:
        model = Teacher
        fields = ['userid', 'username', 'phone', 'school_name', 'college_name', 'identity', 'status', 'create_time', 'teacherID']

class StudentListSerializer(serializers.HyperlinkedModelSerializer):
    class_name = serializers.CharField(source='belong_class.class_name', allow_null=True, default='无')
    grade = serializers.CharField(source='belong_class.grade', allow_null=True, default='无')
    major_name = serializers.CharField(source='belong_class.major.major_name', allow_null=True, default='无')
    college_name = serializers.CharField(source='belong_class.major.college.college_name', allow_null=True, default='无')
    school_name = serializers.CharField(source='belong_class.major.college.school.school_name', allow_null=True, default='无')
    username = serializers.CharField(source='user.real_name')
    userid = serializers.CharField(source='user.id')
    phone = serializers.CharField(source='user.phone')
    status = FormatTransField(source='user.user_status', transname='status')
    create_time = serializers.DateTimeField(format="%Y-%m-%d %H:%M:%S", source='user.create_time')
    
    class Meta:
        model = Student
        fields = ['userid', 'studentID', 'username', 'phone', 'school_name', 'college_name', 'major_name', 'class_name', 'grade', 'status', 'create_time']

class ExpertListSerializer(serializers.HyperlinkedModelSerializer):
    school_name = serializers.CharField(source='school.school_name', allow_blank=True, default='')
    username = serializers.CharField(source='user.real_name')
    userid = serializers.CharField(source='user.id')
    phone = serializers.CharField(source='user.phone')
    status = FormatTransField(source='user.user_status', transname='status')
    create_time = serializers.DateTimeField(format="%Y-%m-%d %H:%M:%S", source='user.create_time')
    
    class Meta:
        model = Expert
        fields = ['userid', 'username', 'phone', 'school_name', 'job_title', 'status', 'create_time']

class ClassListSerializer(serializers.HyperlinkedModelSerializer):
    class_id = serializers.CharField(source='id')
    major_name = serializers.CharField(source='major.major_name', allow_blank=True, default='')
    college_name = serializers.CharField(source='major.college.college_name', allow_blank=True, default='')
    school_name = serializers.CharField(source='major.college.school.school_name', allow_blank=True, default='')
    major_id = serializers.CharField(source='major.id')
    college_id = serializers.CharField(source='major.college.id')
    school_id = serializers.CharField(source='major.college.school.id')
    status = FormatTransField(transname='class_status')
    statusLabel = FormatTransLabelField(source='status', transname='class_status_zh')
    create_time = serializers.DateTimeField(format="%Y-%m-%d %H:%M:%S")
    
    class Meta:
        model = Class
        fields = ['class_id', 'class_name', 'school_id', 'school_name', 'college_id', 'college_name', 'major_id', 'major_name', 'status', 'grade', 'create_time', 'statusLabel']

class TeacherSerializer(serializers.HyperlinkedModelSerializer):
    userid = serializers.CharField(source='user.id')
    real_name = serializers.CharField(source='user.real_name')
    phone = serializers.CharField(source='user.phone')
    email = serializers.CharField(source='user.email')
    sex = serializers.CharField(source='user.sex')
    sexLabel = FormatTransLabelField(source='user.sex', transname='sex_zh')
    identity = FormatTransField(source='teacher_type', transname='teacher_identity')
    identityLabel = FormatTransLabelField(source='teacher_type', transname='teacher_identity_zh')
    status = FormatTransField(source='user.user_status', transname='status')
    statusLabel = FormatTransLabelField(source='user.user_status', transname='status_zh')
    teacherid = serializers.CharField(source='teacherID')
    # school_name = serializers.CharField(source='college.school.school_name', allow_blank=True, default='')
    # school_id = serializers.CharField(source='college.school.id')
    # college_name = serializers.CharField(source='college.college_name', allow_blank=True, default='')
    # course_name = serializers.SlugRelatedField(many=True, read_only=True, slug_field='course_name', source='course')
    # college_id = serializers.CharField(source='college.id')
    create_time = serializers.DateTimeField(format="%Y-%m-%d %H:%M:%S", source='user.create_time')
    openid = serializers.CharField(source='user.openid')
    nickname = serializers.CharField(source='user.nickname')
    avatar = serializers.CharField(source='user.avatar')
    region = serializers.CharField(source='user.region')

    class Meta:
        model = Teacher
        fields = ['userid', 'real_name', 'phone', 'email', 'sex', 'identity', 'status', 'create_time', 'teacherid', 'openid', 'nickname', 'avatar', 'region', 'sexLabel', 'statusLabel', 'identityLabel']

class ExpertSerializer(serializers.HyperlinkedModelSerializer):
    userid = serializers.CharField(source='user.id')
    username = serializers.CharField(source='user.real_name')
    phone = serializers.CharField(source='user.phone')
    email = serializers.CharField(source='user.email')
    sex = FormatTransField(source='user.sex', transname='sex')
    sexLabel = FormatTransLabelField(source='user.sex', transname='sex_zh')
    status = FormatTransField(source='user.user_status', transname='status')
    statusLabel = FormatTransLabelField(source='user.user_status', transname='status_zh')
    school_name = serializers.CharField(source='school.school_name', allow_blank=True, default='')
    school_id = serializers.CharField(source='school.id')
    create_time = serializers.DateTimeField(format="%Y-%m-%d %H:%M:%S", source='user.create_time')
    openid = serializers.CharField(source='user.openid')
    nickname = serializers.CharField(source='user.nickname')
    avatar = serializers.CharField(source='user.avatar')
    region = serializers.CharField(source='user.region')

    class Meta:
        model = Expert
        fields = ['userid', 'username', 'phone', 'email', 'sex', 'job_title', 'status', 'create_time', 'school_name', 'school_id', 'openid', 'nickname', 'avatar', 'region', 'sexLabel', 'statusLabel']

class TeacherCreateSerializer(serializers.HyperlinkedModelSerializer):
    class Meta:
        model = Teacher
        fields = []

class StudentCreateSerializer(serializers.HyperlinkedModelSerializer):
    # studentid = serializers.CharField(source='studentID',allow_blank=True)
    class Meta:
        model = Student
        fields = [ 'admission_date']

class ExpertCreateSerializer(serializers.HyperlinkedModelSerializer):
    class Meta:
        model = Expert
        fields = ['job_title']

class ClassCreateSerializer(serializers.HyperlinkedModelSerializer):
    class Meta:
        model = Class
        fields = ['class_name', 'grade']

class TeacherUpdateSerializer(serializers.HyperlinkedModelSerializer):
    class Meta:
        model = Teacher
        fields = []

class StudentUpdateSerializer(serializers.HyperlinkedModelSerializer):
    # studentid = serializers.CharField(source='studentID', required=False)
    # studentid = serializers.CharField(source='studentID', allow_blank=True)
    # admission_date = serializers.DateField(required=False,allow_blank=True)
    class Meta:
        model = Student
        fields = ['admission_date']

class ExpertUpdateSerializer(serializers.HyperlinkedModelSerializer):
    job_title = serializers.CharField(required=False)
    class Meta:
        model = Expert
        fields = ['job_title']

class ClassUpdateSerializer(serializers.HyperlinkedModelSerializer):
    class Meta:
        model = Class
        fields = ['class_name', 'grade']

class TeacherListBlockSerializer(serializers.ListSerializer):
    def update(self, instance, validated_data):
        teacher_mapping = {teacher.id: teacher for teacher in instance}
        status = trans.status[validated_data["status"]]
        print(teacher_mapping)
        print(status)

class TeacherBlockSerializer(serializers.ModelSerializer):
    userid = serializers.CharField(source='user.id')
    status = FormatTransField(source='user.user_status', transname='status')
    class Meta:
        model = Teacher
        fields = ['userid','status']

class StudentBlockSerializer(serializers.ModelSerializer):
    userid = serializers.CharField(source='user.id')
    status = FormatTransField(source='user.user_status', transname='status')
    class Meta:
        model = Student
        fields = ['userid','status']

class ExpertBlockSerializer(serializers.ModelSerializer):
    userid = serializers.CharField(source='user.id')
    status = FormatTransField(source='user.user_status', transname='status')
    class Meta:
        model = Expert
        fields = ['userid','status']

class ClassBlockSerializer(serializers.ModelSerializer):
    class_id = serializers.CharField(source='id')
    class_status = FormatTransField(source='status', transname='class_status')
    class Meta:
        model = Class
        fields = ['class_id','class_status']

class GroupSerializer(serializers.HyperlinkedModelSerializer):
    class Meta:
        model = Group
        fields = ['url', 'name']

class KnowledgeSerializer(serializers.ModelSerializer):
    knowledge_path = serializers.SerializerMethodField()

    class Meta:
        model = Knowledge
        fields = ['id', 'knowledge_name', 'knowledge_path']

    def get_knowledge_path(self, obj):
        res = obj.knowledge_name
        temp = obj.parent
        while temp!= None:
            res = temp.knowledge_name + '/' + res
            temp = temp.parent
        return res

class StudentSerializer(serializers.HyperlinkedModelSerializer):
    userid = serializers.CharField(source='user.id')
    user_id = serializers.CharField(source='user.username')
    username = serializers.CharField(source='user.real_name')
    phone = serializers.CharField(source='user.phone')
    email = serializers.CharField(source='user.email')
    sex = FormatTransField(source='user.sex', transname='sex')
    sexLabel = FormatTransLabelField(source='user.sex', transname='sex_zh')
    status = FormatTransField(source='user.user_status', transname='status')
    statusLabel = FormatTransLabelField(source='user.user_status', transname='status_zh')
    studentid = serializers.CharField(source='studentID')
    school_name = serializers.CharField(source='belong_class.major.college.school.school_name', allow_null=True)
    school_id = serializers.CharField(source='belong_class.major.college.school.id', allow_null=True)
    college_name = serializers.CharField(source='belong_class.major.college.college_name', allow_null=True)
    college_id = serializers.CharField(source='belong_class.major.college.id', allow_null=True)
    major_name = serializers.CharField(source='belong_class.major.major_name', allow_null=True)
    major_id = serializers.CharField(source='belong_class.major.id', allow_null=True)
    class_name = serializers.CharField(source='belong_class.class_name', allow_null=True)
    class_id = serializers.CharField(source='belong_class.id', allow_null=True)
    create_time = serializers.DateTimeField(format="%Y-%m-%d %H:%M:%S", source='user.create_time')
    openid = serializers.CharField(source='user.openid')
    nickname = serializers.CharField(source='user.nickname')
    avatar = serializers.CharField(source='user.avatar')
    region = serializers.CharField(source='user.region')

    class Meta:
        model = Student
        fields = ['userid', 'user_id', 'username', 'phone', 'email', 'sex', 'admission_date', 'create_time', 'status', 'studentid', 'school_name', 'school_id', 'college_name', 'college_id', 'major_name', 'major_id', 'class_name', 'class_id', 'openid', 'nickname', 'avatar', 'region', 'sexLabel', 'statusLabel']

class ClassSerializer(serializers.HyperlinkedModelSerializer):
    class_id = serializers.CharField(source='id')
    major_name = serializers.CharField(source='major.major_name')
    college_name = serializers.CharField(source='major.college.college_name')
    school_name = serializers.CharField(source='major.college.school.school_name')
    status = FormatTransField(transname='status')
    statusLabel = FormatTransField(source='status', transname='class_status_zh')
    create_time = serializers.DateTimeField(format="%Y-%m-%d %H:%M:%S")
    
    class Meta:
        model = Class
        fields = ['class_id', 'class_name', 'school_name', 'college_name', 'major_name', 'status', 'grade', 'create_time', 'statusLabel']


class FuzzySearchSchoolSerializer(serializers.ModelSerializer):
    school_id = serializers.CharField(source='id')
    class Meta:
        model = School
        fields = ['school_id','school_name']

class FuzzySearchCollegeSerializer(serializers.ModelSerializer):
    college_id = serializers.CharField(source='id')
    school_name = serializers.CharField(source='school.school_name')
    class Meta:
        model = College
        fields = ['college_id', 'college_name', 'school_name']
        
class FuzzySearchMajorSerializer(serializers.ModelSerializer):
    major_id = serializers.CharField(source='id')
    college_name = serializers.CharField(source='college.college_name')
    school_name = serializers.CharField(source='college.school.school_name')
    class Meta:
        model = Major
        fields = ['major_id', 'major_name', 'college_name', 'school_name']

class FuzzySearchClassSerializer(serializers.ModelSerializer):
    class_id = serializers.CharField(source='id')
    major_name = serializers.CharField(source='major.major_name')
    college_name = serializers.CharField(source='major.college.college_name')
    school_name = serializers.CharField(source='major.college.school.school_name')
    class Meta:
        model = Class
        fields = ['class_id', 'class_name', 'major_name', 'college_name', 'school_name']

# 章节
class RecursiveSerializer(serializers.Serializer):
    def to_representation(self, value):
        serializer = self.parent.parent.__class__(value, context=self.context)
        return serializer.data

class ChapterListSerializer(serializers.ModelSerializer):
    create_time = serializers.DateTimeField(format="%Y-%m-%d %H:%M:%S")

    class Meta:
        model = Chapter
        fields = ('id', 'chapter_name', 'detail_type', 'status', 'create_time', 'pv')

# 课程


class TeacherNameSerializer(serializers.ModelSerializer):
    name = serializers.CharField(source='user.real_name')
    class Meta:
        model = Teacher
        fields = ['name']

class CourseCreateSerializer(serializers.ModelSerializer):
    # avatar_url = serializers.FileField(source='avatar.location', use_url=True, read_only=True)
    # course_type = FormatTransField(transname='course_type', read_only=True)
    # course_status = FormatTransField(source='status', transname='class_status', read_only=True)

    class Meta:
        model = Course
        fields = ['id', 'course_name', 'describe', 'avatar_id', 'price']

class CourseUpdateSerializer(serializers.ModelSerializer):
    # avatar_url = serializers.FileField(source='avatar.location', use_url=True, read_only=True)
    # course_type = FormatTransField(transname='course_type', read_only=True)
    course_name = serializers.CharField(required=False)
    # course_status = FormatTransField(source='status', transname='class_status', read_only=True)

    class Meta:
        model = Course
        fields = ['id', 'course_name', 'describe', 'avatar_id', 'choice_code', 'capacity', 'price']

class CourseSerializer(serializers.ModelSerializer):
    avatar_url = serializers.SerializerMethodField()
    course_type = FormatTransField(transname='course_type', read_only=True)
    # status = FormatTransField(transname='class_status', read_only=True)
    teacher_set = TeacherNameSerializer(many=True, read_only=True)
    student_count = serializers.SerializerMethodField()
    choiced = serializers.SerializerMethodField()
    teacher_names = serializers.SerializerMethodField()
    create_time = serializers.DateTimeField(format="%Y-%m-%d %H:%M:%S")

    class Meta:
        model = Course
        fields = ['id', 'course_name', 'describe', 'status', 'avatar_id', 'avatar_url', 'course_type', 'theo_hours', 'prac_hours', 'credit', 'capacity', 'choice_code', 'student_count', 'choiced', 'teacher_set', 'price', 'teacher_names', 'editor', 'create_time']

    def get_student_count (self, obj):
        return obj.student_set.count()

    def get_avatar_url(self, obj):
        return settings.MEDIA_HOST + obj.avatar.location.url
    
    def get_choiced(self, obj):
        try:
            return Student.choicedCourse(self.context['request'].user.student, obj.id)
        except Exception as e:
            return 0

    def get_teacher_names(self, obj):
        res = ''
        for c in Teacher.objects.filter(course=obj).all():
            res += '、' + c.user.real_name
        return res[1:]


class CourseBlockSerializer(serializers.ModelSerializer):
    course_id = serializers.CharField(source='id')
    status = FormatTransField(transname='class_status')
    class Meta:
        model = Class
        fields = ['course_id','status']

class KnowledgeNameSerializer(serializers.ModelSerializer):
    name = serializers.CharField(source='knowledge_name')
    class Meta:
        model = Knowledge
        fields = ['name']

class ChapterSerializer(serializers.HyperlinkedModelSerializer):
    knowledge_set = KnowledgeNameSerializer(many=True, read_only=True)
    detail = serializers.CharField(required=False)
    detail_type = serializers.CharField(required=False)
    chapter_name = serializers.CharField(required=False)
    chapter_path = serializers.SerializerMethodField()
    attach_url = serializers.SerializerMethodField()

    class Meta:
        model = Chapter
        fields = ('chapter_path', 'id', 'chapter_name', 'knowledge_set', 'detail', 'detail_type', 'attach_url', 'parent_id')
    
    def get_chapter_path(self, obj):
        res = obj.chapter_name
        temp = obj.parent
        while temp!= None:
            res = temp.chapter_name + '/' + res
            temp = temp.parent
        return res

    def get_attach_url(self, obj):
        if obj.detail_type in ['V', 'P']:
            return sign_rich_attach_url(obj.detail)
        else:
            return ''

""" class ExperimentListSerializer(serializers.ModelSerializer):
    chapter_name = serializers.CharField(source='chapter.chapter_name')

    class Meta:
        model = Experiment
        fields = ('chapter_name', 'id', 'experiment_name', 'duration', 'ending_time') """

class CourseStudentListSerializer(serializers.ModelSerializer):
    choose_time = serializers.SerializerMethodField()
    userid = serializers.CharField(source='user.id')
    class_name = serializers.CharField(source='belong_class.class_name', allow_blank=True, default='')
    grade = serializers.CharField(source='belong_class.grade', allow_blank=True, default='')
    major_name = serializers.CharField(source='belong_class.major.major_name', allow_blank=True, default='')
    college_name = serializers.CharField(source='belong_class.major.college.college_name', allow_blank=True, default='')
    school_name = serializers.CharField(source='belong_class.major.college.school.school_name', allow_blank=True, default='')
    username = serializers.CharField(source='user.real_name')
    studentid = serializers.CharField(source='studentID')

    class Meta:
        model = Student
        fields = ('userid', 'username', 'school_name', 'college_name', 'major_name', 'class_name', 'grade', 'choose_time', 'studentid')

    def get_choose_time(self, obj):
        return StudentCourse.objects.get(student__id=obj.id, course__id=self.context['course_id']).choose_time

class CourseTeacherListSerializer(serializers.ModelSerializer):
    userid = serializers.CharField(source='user.id')
    college_name = serializers.CharField(source='college.college_name', allow_blank=True, default='')
    school_name = serializers.CharField(source='college.school.school_name', allow_blank=True, default='')
    username = serializers.CharField(source='user.real_name')
    phone = serializers.CharField(source='user.phone')

    class Meta:
        model = Teacher
        fields = ('userid', 'username', 'school_name', 'college_name', 'phone', 'teacherID')

class SchoolListSerializer(serializers.HyperlinkedModelSerializer):
    school_id = serializers.CharField(source='id')
    create_time = serializers.DateTimeField(format="%Y-%m-%d %H:%M:%S")
    
    class Meta:
        model = School
        fields = ['school_id', 'school_name', 'level', 'create_time', 'status']

class SchoolCreateSerializer(serializers.HyperlinkedModelSerializer):
    class Meta:
        model = School
        fields = ['school_name', 'level']

class SchoolUpdateSerializer(serializers.HyperlinkedModelSerializer):
    school_name = serializers.CharField(required=False)
    level = serializers.CharField(required=False)
    status = serializers.CharField(required=False)

    class Meta:
        model = School
        fields = ['school_name', 'level', 'status']
    
    def update(self, instance, validated_data):
        instance.status = validated_data.get('status', instance.status)
        instance.school_name = validated_data.get('school_name', instance.school_name)
        return super().update(instance, validated_data)

class CollegeListSerializer(serializers.HyperlinkedModelSerializer):
    college_id = serializers.CharField(source='id')
    school_name = serializers.CharField(source='school.school_name')
    create_time = serializers.DateTimeField(format="%Y-%m-%d %H:%M:%S")
    
    class Meta:
        model = College
        fields = ['college_id', 'school_name', 'college_name', 'create_time', 'status']

class CollegeCreateSerializer(serializers.HyperlinkedModelSerializer):

    class Meta:
        model = College
        fields = ['college_name']

class CollegeUpdateSerializer(serializers.HyperlinkedModelSerializer):
    college_name = serializers.CharField(required=False)

    class Meta:
        model = College
        fields = ['college_name', 'status', 'school_id']

    def update(self, instance, validated_data):
        instance.status = validated_data.get('status', instance.status)
        instance.college_name = validated_data.get('college_name', instance.college_name)
        instance.school_id = validated_data.get('school_id', instance.school_id)
        return super().update(instance, validated_data)

class MajorListSerializer(serializers.HyperlinkedModelSerializer):
    major_id = serializers.CharField(source='id')
    school_name = serializers.CharField(source='college.school.school_name')
    college_name = serializers.CharField(source='college.college_name')
    create_time = serializers.DateTimeField(format="%Y-%m-%d %H:%M:%S")
    
    class Meta:
        model = Major
        fields = ['major_id', 'major_name', 'school_name', 'college_name', 'status', 'create_time']

class MajorCreateSerializer(serializers.HyperlinkedModelSerializer):

    class Meta:
        model = Major
        fields = ['major_name']

class MajorUpdateSerializer(serializers.HyperlinkedModelSerializer):
    major_name = serializers.CharField(required=False)

    class Meta:
        model = Major
        fields = ['major_name', 'status', 'college_id']
    
    def update(self, instance, validated_data):
        instance.status = validated_data.get('status', instance.status)
        instance.major_name = validated_data.get('major_name', instance.major_name)
        instance.college_id = validated_data.get('college_id', instance.college_id)
        return super().update(instance, validated_data)

class KnowledgeListSerializer(serializers.ModelSerializer):

    class Meta:
        model = Knowledge
        fields = ('parent', 'id', 'knowledge_name')

class KnowledgeSearchListSerializer(serializers.ModelSerializer):
    knowledge_path = serializers.SerializerMethodField()

    class Meta:
        model = Knowledge
        fields = ('id', 'knowledge_name', 'knowledge_path')

    def get_knowledge_path(self, obj):
        res = obj.knowledge_name
        temp = obj.parent
        while temp!= None:
            res = temp.knowledge_name + '/' + res
            temp = temp.parent
        return res

class ImageUploadSerializer(serializers.ModelSerializer):
    location = serializers.FileField(allow_empty_file=True, use_url=True, required=False, write_only=True, validators=[FileValidator(max_size=2*1024*1024*1024, allowed_extensions=('png','jpg','gif','jpeg','svg', 'doc', 'xlsx', 'zip', 'mp4', 'mov', 'wav', 'mkv', 'pdf'), allowd_mimetypes=('image/png','image/jpeg','image/gif','image/svg+xml', 'application/pdf', 'application/zip', 'video/mp4', 'video/*', 'video/mov', 'video/mkv', 'video/wav'))])
    attach_url = serializers.SerializerMethodField()
    # file_name = serializers.SerializerMethodField()

    class Meta:
        model = RichTextAttach
        fields = ['id', 'location', 'attach_url']

    def get_attach_url(self, obj):
        return sign_attach_url(obj.location.url)
        
    def create(self, validated_data):
        # validated_data['location']= str(uuid.uuid4()) + '.' + validated_data['location'].name.split('.')[-1]
        return super().create(validated_data)


    # def get_file_name(self, obj):
    #     return obj.location.url

class TeacherNameSerializer(serializers.ModelSerializer):
    name = serializers.CharField(source='user.real_name')
    class Meta:
        model = Teacher
        fields = ['name']

class StudentCountMixin():

    def get_student_count(self, obj):
        return obj.student.count()
    
class EnvironmentSerializer(serializers.ModelSerializer):
    experiment_id = serializers.SerializerMethodField()
    create_time = serializers.DateTimeField(format="%Y-%m-%d %H:%M:%S")
    image = serializers.SerializerMethodField()
    is_open = FormatTransField(transname='is_open', read_only=True)

    class Meta:
        model = Environment
        fields = ['id', 'environment_name', 'image', 'subnet_name', 'cidr_block', 'is_open', 'create_time','experiment_id', 'security_group']

    def get_image(self, obj):
        images = obj.image.all()
        res = ""
        for image in images:
            res += "、" + image.image_name if res != "" else image.image_name
        return res

    def get_experiment_id(self, obj):
        experiment = obj.experiment
        return experiment.id if experiment is not None else None


class ExperimentSerializer(serializers.ModelSerializer):
    create_time = serializers.DateTimeField(format="%Y-%m-%d %H:%M:%S")

    class Meta:
        model = Experiment
        # fields = ['id', 'experiment_name', 'type', 'price', 'detail_type', 'describe', 'duration', 'environment_id', 'intro', 'create_time', 'status']
        fields = ['id', 'experiment_name', 'type', 'price', 'detail_type','intro', 'duration', 'environment_id', 'create_time', 'status']

class ExperimentChapterSerializer(serializers.ModelSerializer):
    create_time = serializers.DateTimeField(format="%Y-%m-%d %H:%M:%S")

    class Meta:
        model = ExperimentChapter
        fields = ['id', 'create_time', 'detail', 'experiment_id', 'pv']


class EnvironmentListSerializer(serializers.HyperlinkedModelSerializer):
    images = serializers.SerializerMethodField()
    live_ins_count = serializers.SerializerMethodField()
    create_time = serializers.DateTimeField(format="%Y-%m-%d %H:%M:%S")
    is_open = FormatTransField(transname='is_open', read_only=True)
    
    class Meta:
        model = Environment
        fields = ['id', 'environment_name', 'images', 'subnet_name', 'cidr_block', 'is_open', 'create_time','live_ins_count']

    def get_images(self, obj):
        res = obj.image.all()
        if obj.experiment.experiment_type=='double':
            if len(res) == 1:
               return res[0].image_name+" : "+res[0].image_name
            else:
               experiment_primary_id = obj.experiment.primary_image_id
               pii =''
               cii =''
               for image in res:
                   if int(image.id) == int(experiment_primary_id):
                       pii = image.image_name
                   else:
                       cii=image.image_name
               return pii +" : "+ cii
        if len(res) == 1:
            return res[0].image_name
        return ''


    # def get_images(self, obj):
    #     images = obj.image.all()
    #     res = ""
    #     for image in images:
    #         # res += "、" + image.image_name if res != "" else image.image_name
    #     return res

    def get_live_ins_count(self, obj):

        return Instance.objects.filter(environment_id=obj.id).exclude(status='C').count()

class FuzzySearchImageSerializer(serializers.ModelSerializer):
    image_id = serializers.CharField(source='id')
    class Meta:
        model = Image
        fields = ['image_id','image_name']

class ImageListSerializer(serializers.HyperlinkedModelSerializer):
    create_time = serializers.DateTimeField(format="%Y-%m-%d %H:%M:%S")
    image_type = FormatTransField(transname='image_type', read_only=True)
    
    class Meta:
        model = Image
        fields = ['id', 'image_name', 'opration_system', 'version', 'platform', 'image_type', 'import_status', 'import_msg', 'create_time', 'status']

class CvmImageImportSerializer(serializers.ModelSerializer):
    image_source = serializers.FileField(allow_empty_file=True, use_url=True, required=False, write_only=True)
    operation_system = serializers.CharField(source='opration_system')

    class Meta:
        model = Image
        fields = ['id', 'image_name', 'image_source', 'operation_system', 'imageId', 'task_id', 'architecture', 'platform', 'version']

class CvmImageCreateImportSerializer(serializers.ModelSerializer):
    image_source = serializers.CharField(required=True, write_only=True)
    operation_system = serializers.CharField(source='opration_system')

    class Meta:
        model = Image
        fields = ['image_name', 'image_source', 'image_url', 'operation_system', 'architecture', 'platform', 'version']

class ImageSerializer(serializers.ModelSerializer):
    create_time = serializers.DateTimeField(format="%Y-%m-%d %H:%M:%S")
    image_type = FormatTransField(transname='image_type', read_only=True)
    status = FormatTransField(transname='class_status')

    class Meta:
        model = Image
        fields = '__all__' 

class ImageRemoveSerializer(serializers.ModelSerializer):
    image_id = serializers.CharField(source='id')
    status = FormatTransField(transname='class_status')
    class Meta:
        model = Image
        fields = ['image_id','status']

class FileUploadSerializer(serializers.Serializer):
    # 如果是简单文件上传，可能只需要一个文件字段
    file = serializers.FileField()


class ExperimentScoreListSerializer(serializers.ModelSerializer):
    
    knowledges = serializers.SerializerMethodField()
    experiment = serializers.CharField()

    class Meta:
        model = Report
        fields = ('id', 'title', 'experiment', 'knowledges', 'score')

    def get_knowledges(self, obj):
        knowledges = obj.experiment.knowledge.all()
        res = ""
        for knowledge in knowledges:
            res += "、" + knowledge.knowledge_name if res != "" else knowledge.knowledge_name
        return res

class ExamScoreListSerializer(serializers.ModelSerializer):
    
    exam_name = serializers.CharField(source='exam.exam_name')
    start_time = serializers.DateTimeField(source='exam.start_time', format="%Y-%m-%d %H:%M:%S")
    duration = serializers.CharField(source='exam.duration')

    class Meta:
        model = Paper
        fields = ('id', 'exam_name', 'start_time', 'duration', 'score')

class ExperimentCreateSerializer(serializers.ModelSerializer):
    # experiment_name = serializers.CharField(source='experiment_name')

    class Meta:
        model = Experiment
        fields = ['experiment_name', 'describe', 'editor', 'ending_time', 'duration']

class EnvironmentCreateSerializer(serializers.ModelSerializer):

    class Meta:
        model = Environment
        fields = ['id']

class ExperimentRemoveSerializer(serializers.ModelSerializer):
    experiment_id = serializers.CharField(source='id')
    status = FormatTransField(transname='class_status')
    class Meta:
        model = Experiment
        fields = ['experiment_id','status']

class QuestionListSerializer(serializers.ModelSerializer):
    
    knowledges = serializers.SerializerMethodField()
    question_name = serializers.SerializerMethodField()
    create_time = serializers.DateTimeField(format="%Y-%m-%d %H:%M:%S")

    class Meta:
        model = Question
        fields = ('id', 'question_name', 'knowledges', 'create_time', 'question_type')

    def get_knowledges(self, obj):
        knowledges = obj.knowledge.all()
        res = ""
        for knowledge in knowledges:
            res += "、" + knowledge.knowledge_name if res != "" else knowledge.knowledge_name
        return res

    def get_question_name(self, obj):
        if obj.question_type in ['MA','MC','TF']:
            return obj.choicedetail.describe if hasattr(obj,'choicedetail') else ''
        else:
            return obj.blankdetail.describe if hasattr(obj,'blankdetail') else ''

class BlankQuestionCreateSerializer(serializers.ModelSerializer):

    class Meta:
        model = Question
        fields = ['id']

class ChoiceQuestionCreateSerializer(serializers.ModelSerializer):

    class Meta:
        model = Question
        fields = ['id']

class ChoiceQuestionSerializer(serializers.ModelSerializer):
    create_time = serializers.DateTimeField(format="%Y-%m-%d %H:%M:%S")
    question_name = serializers.CharField(source='choicedetail.describe')
    status = FormatTransField(transname='class_status')
    # option_detail = seria lizers.SlugRelatedField(many=True, read_only=True, slug_field='content', source='choicedetail.optiondetail_set')
    knowledges = KnowledgeSerializer(many=True, read_only=True, source='knowledge')
    option_detail = serializers.SerializerMethodField()

    class Meta:
        model = Question
        fields = ['id','question_type','question_name','option_detail','knowledges','create_time','status']
    
    def get_option_detail(self, obj):
        choiceDetail = ChoiceDetail.objects.filter(question=obj.id).first()
        ods = OptionDetail.objects.filter(choice_detail=choiceDetail).values()
        print('ods: {}'.format(ods))
        return ods


class BlankQuestionSerializer(serializers.ModelSerializer):
    create_time = serializers.DateTimeField(format="%Y-%m-%d %H:%M:%S")
    question_name = serializers.CharField(source='blankdetail.describe')
    status = FormatTransField(transname='class_status')
    knowledges = KnowledgeSerializer(many=True, read_only=True, source='knowledge')
    answer = serializers.CharField(source='blankdetail.answer')

    class Meta:
        model = Question
        fields = ['id','question_type','question_name','judge_type','answer','knowledges','create_time','status']  

class KnowledgeDetailSerializer(serializers.ModelSerializer):
    knowledge_path = serializers.SerializerMethodField()

    class Meta:
        model = Knowledge
        fields = ['id', 'knowledge_name', 'knowledge_path']

    def get_knowledge_path(self, obj):
        res = obj.knowledge_name
        temp = obj.parent
        while temp!= None:
            res = temp.knowledge_name + '/' + res
            temp = temp.parent
        return res

class OptionDetailSerializer(serializers.ModelSerializer):

    class Meta:
        model = OptionDetail
        fields = ['id', 'content', 'is_correct']

class ChoiceQuestionUpdateSerializer(serializers.ModelSerializer):

    class Meta:
        model = Question
        fields = ['id']

class OptionDetailCreateSerializer(serializers.ModelSerializer):

    class Meta:
        model = OptionDetail
        fields = ['id']

class BlankQuestionUpdateSerializer(serializers.ModelSerializer):

    class Meta:
        model = Question
        fields = ['id']
"""
当attach中file_type为D或Z时，该对象为“报告附件”；当file_type为I时，该对象为“实验截图”；当file_type为V时，该对象为“实验录屏”
"""
class AttachSerializer(serializers.ModelSerializer):

    attach_url = serializers.FileField(source='location', use_url=True, read_only=True)

    class Meta:
        model = Attach
        fields = ['attach_url', 'file_name', 'file_type']

class AccessLogSerializer(serializers.ModelSerializer):

    instance_name = serializers.CharField(source='instance.name')
    access_time = serializers.DateTimeField(format="%Y-%m-%d %H:%M:%S")
    access_length = serializers.SerializerMethodField()

    class Meta:
        model = AccessLog
        fields = ['id', 'instance_name', 'access_time', 'access_length']

    def get_access_length(self, obj):
        access_time = obj.access_time
        update_time = obj.update_time
        delta = (update_time - access_time).seconds
        return str(delta)+"秒" if delta <60 else str(int(delta/60))+"分"+str(int(delta%60))+"秒"

class OperateLogSerializer(serializers.ModelSerializer):

    attach_url = serializers.FileField(source='location', use_url=True, read_only=True)
    operate_time = serializers.DateTimeField(format="%Y-%m-%d %H:%M:%S")

    class Meta:
        model = Attach
        fields = ['id','attach_url', 'operate_time']

class ReportSerializer(serializers.ModelSerializer):

    experiment_name = serializers.CharField(source='experiment.experiment_name')
    submit_time = serializers.DateTimeField(format="%Y-%m-%d %H:%M:%S")
    username = serializers.CharField(source='student.user.real_name')
    studentID = serializers.CharField(source='student.studentID')
    attach = AttachSerializer(many=True, read_only=True, source='attach_set')
    access_log = serializers.SerializerMethodField()
    operate_log = serializers.SerializerMethodField()

    class Meta:
        model = Report
        fields = ['id', 'title', 'experiment_name', 'studentID', 'username', 'submit_time', 'score', 'comment', 'content', 'attach', 'access_log', 'operate_log']

    def get_access_log(self, obj):
        try:
            student = obj.student
            environment = obj.experiment.environment
            instance = Instance.objects.get(student=student, environment=environment)
            accesslogs = AccessLog.objects.filter(instance=instance)
            return AccessLogSerializer(accesslogs, many=True).data
        except:
            return []

    def get_operate_log(self, obj):
        try:
            student = obj.student
            environment = obj.experiment.environment
            instance = Instance.objects.get(student=student, environment=environment)
            operatelogs = OperateLog.objects.filter(instance=instance)
            return OperateLogSerializer(operatelogs, many=True).data
        except:
            return []

class ReportScoreSerializer(serializers.ModelSerializer):

    class Meta:
        model = Report
        fields = ['id','score', 'comment']

class ExamCreateSerializer(serializers.HyperlinkedModelSerializer):
    start_time = serializers.DateTimeField(format="%Y-%m-%d %H:%M:%S", allow_null=True, default=None, write_only=True)
    duration = serializers.IntegerField(write_only=True)
    exam_name = serializers.CharField(write_only=True)
    exam_describe = serializers.CharField(write_only=True, required=False)

    class Meta:
        model = Exam
        fields = ['id', 'start_time', 'duration', 'exam_name', 'exam_describe', 'price']

class ChoiceOptionSerializer(serializers.ModelSerializer):

    class Meta:
        model = OptionDetail
        fields = ['id', 'content']

class ChoiceQuestionDetailSerializer(serializers.ModelSerializer):

    options = serializers.SerializerMethodField()
    # serializers.SlugRelatedField(many=True, read_only=True, slug_field='content', source='question.choicedetail.optiondetail_set')
    describe = serializers.SerializerMethodField()
    # serializers.CharField(source='question.choicedetail.describe')
    question_id = serializers.SerializerMethodField()

    class Meta:
        model = ExamQuestion
        fields = ['id', 'value', 'describe', 'options', 'question_id']

    def get_options(self, obj):
        try:
            optiondetails = obj.question.choicedetail.optiondetail_set
            return ChoiceOptionSerializer(optiondetails, many=True).data
        except:
            return []

    def get_describe(self, obj):
        try:
            return obj.question.choicedetail.describe
        except:
            return ""

    def get_question_id(self, obj):
        try:
            return obj.question.id
        except:
            return None

class BlankQuestionDetailSerializer(serializers.ModelSerializer):

    describe = serializers.SerializerMethodField()
    # serializers.CharField(source='question.blankdetail.describe')
    question_id = serializers.SerializerMethodField()

    class Meta:
        model = ExamQuestion
        fields = ['id', 'value', 'describe', 'question_id']

    def get_describe(self, obj):
        try:
            return obj.question.blankdetail.describe
        except:
            return ""

    def get_question_id(self, obj):
        try:
            return obj.question.id
        except:
            return None

class ExamSerializer(serializers.HyperlinkedModelSerializer, StudentCountMixin):
    start_time = serializers.DateTimeField(format="%Y-%m-%d %H:%M:%S")
    create_time = serializers.DateTimeField(format="%Y-%m-%d %H:%M:%S")
    mc = serializers.SerializerMethodField()
    ma = serializers.SerializerMethodField()
    tf = serializers.SerializerMethodField()
    bl = serializers.SerializerMethodField()
    sa = serializers.SerializerMethodField()
    student_count = serializers.SerializerMethodField()
    paper_count = serializers.SerializerMethodField()

    class Meta:
        model = Exam
        fields = ['id', 'start_time', 'duration', 'exam_name', 'exam_describe', 'create_time', 'ma_total', 'mc_total', 'tf_total', 'bl_total', 'sa_total', 'question_total', 'mc' ,'ma', 'tf', 'bl', 'sa', 'price', 'student_count', 'paper_count', 'ma_score', 'mc_score', 'tf_score', 'bl_score', 'sa_score']

    def get_mc(self, obj):
        eq = ExamQuestion.objects.filter(exam__id=obj.id, question_type='MC').order_by('order')
        return ChoiceQuestionDetailSerializer(eq, many=True).data

    def get_ma(self, obj):
        eq = ExamQuestion.objects.filter(exam__id=obj.id, question_type='MA').order_by('order')
        return ChoiceQuestionDetailSerializer(eq, many=True).data

    def get_tf(self, obj):
        eq = ExamQuestion.objects.filter(exam__id=obj.id, question_type='TF').order_by('order')
        return ChoiceQuestionDetailSerializer(eq, many=True).data

    def get_bl(self, obj):
        eq = ExamQuestion.objects.filter(exam__id=obj.id, question_type='BL').order_by('order')
        return BlankQuestionDetailSerializer(eq, many=True).data

    def get_sa(self, obj):
        eq = ExamQuestion.objects.filter(exam__id=obj.id, question_type='SA').order_by('order')
        return BlankQuestionDetailSerializer(eq, many=True).data

    def get_paper_count(self, obj):
        return Paper.objects.filter(exam=obj).count()
    
class ExamUpdateSerializer(serializers.ModelSerializer):

    start_time = serializers.DateTimeField(format="%Y-%m-%d %H:%M:%S", required=False)
    duration = serializers.IntegerField(required=False)
    exam_name = serializers.CharField(required=False)

    class Meta:
        model = Exam
        fields = ['exam_name', 'start_time', 'duration']
    
class ExamListSerializer(serializers.ModelSerializer, StudentCountMixin):

    exam_name = serializers.CharField()
    start_time = serializers.DateTimeField(format="%Y-%m-%d %H:%M:%S")
    create_time = serializers.DateTimeField(format="%Y-%m-%d %H:%M:%S")
    duration = serializers.IntegerField()
    question_total = serializers.IntegerField()
    student_count = serializers.SerializerMethodField()

    class Meta:
        model = Exam
        fields = ['id', 'exam_name', 'start_time', 'duration', 'question_total', 'exam_describe', 'price', 'student_count', 'status', 'create_time']

    def get_exam_status(self, obj):
        return "已考试" if obj.start_time < datetime.now() is not None else "未考试"

class PaperListSerializer(serializers.ModelSerializer):

    paper_name = serializers.CharField(source='exam.exam_name')
    course_name = serializers.CharField(source='exam.course.course_name')
    start_time = serializers.DateTimeField(format="%Y-%m-%d %H:%M:%S", source='exam.start_time')
    duration = serializers.IntegerField(source='exam.duration')
    username = serializers.CharField(source='student.user.real_name')
    studentid = serializers.CharField(source='student.studentID')
    question_total = serializers.IntegerField(source='exam.question_total')
    paper_status = serializers.SerializerMethodField()

    class Meta:
        model = Paper
        fields = ['id', 'paper_name', 'course_name', 'username', 'studentid', 'start_time', 'duration', 'score', 'comment', 'question_total', 'paper_status']

    def get_paper_status(self, obj):
        return "已评分" if obj.score is not None else "未评分"

class PaperChoiceQuestionDetailSerializer(serializers.ModelSerializer):

    options = serializers.SerializerMethodField()
    # serializers.SlugRelatedField(many=True, read_only=True, slug_field='content', source='question.choicedetail.optiondetail_set')
    describe = serializers.SerializerMethodField()
    # serializers.CharField(source='question.choicedetail.describe')
    question_id = serializers.SerializerMethodField()
    # answer = serializers.BooleanField(source='question__question__choicedetail__')
    value = serializers.IntegerField(source='question.value')
    student_answer = serializers.SerializerMethodField()
    standard_answer = serializers.SerializerMethodField()
    student_answer_display = serializers.SerializerMethodField()
    standard_answer_display = serializers.SerializerMethodField()
    class Meta:
        model = PaperQuestion
        fields = ['id', 'value', 'describe', 'options', 'question_id', 'originscore', 'correctscore', 'is_correct', 'standard_answer', 'student_answer', 'standard_answer_display', 'student_answer_display']

    def get_options(self, obj):
        try:
            optiondetails = obj.question.question.choicedetail.optiondetail_set
            return ChoiceOptionSerializer(optiondetails, many=True).data
        except:
            return []

    def get_describe(self, obj):
        try:
            return obj.question.question.choicedetail.describe
        except:
            return ""

    def get_question_id(self, obj):
        try:
            return obj.question.question.id
        except:
            return None

    def get_standard_answer(self, obj):
        try:
            optiondetails = obj.question.question.choicedetail.optiondetail_set.all()
            stan = []
            for od in optiondetails:
                if od.is_correct == True:
                    stan.append(od.id)
            return stan
        except Exception as e:
            print(e)
            return []

    
    def get_standard_answer_display(self, obj):
        try:
            optiondetails = obj.question.question.choicedetail.optiondetail_set.all()
            stan = []
            ord = 65
            for od in optiondetails:
                if od.is_correct == True:
                    stan.append(chr(ord))
                ord += 1 
            return stan
        except Exception as e:
            print(e)
            return []

    def get_student_answer(self, obj):
        try:
            optiondetails = obj.choice_answer.all()
            stan = []
            for od in optiondetails:
                stan.append(od.id)
            return stan
        except Exception as e:
            print(e)
            return []
        
    def get_student_answer_display(self, obj):
        try:
            options = obj.question.question.choicedetail.optiondetail_set.all()
            optiondetails = list(obj.choice_answer.all().values_list('id', flat=True))
            stan = []
            ord = 65
            for od in options:
                if od.id in optiondetails:
                    stan.append(chr(ord))
                ord += 1 
            return stan
        except Exception as e:
            print(e)
            return []
            
class PaperBlankQuestionDetailSerializer(serializers.ModelSerializer):

    describe = serializers.SerializerMethodField()
    # serializers.CharField(source='question.blankdetail.describe')
    question_id = serializers.SerializerMethodField()
    value = serializers.IntegerField(source='question.value')
    standard_answer =  serializers.CharField(source='question.question.blankdetail.answer')
    student_answer = serializers.CharField(source='blank_answer')

    class Meta:
        model = PaperQuestion
        fields = ['id', 'value', 'describe', 'originscore', 'correctscore', 'question_id', 'standard_answer', 'student_answer']

    def get_describe(self, obj):
        try:
            return obj.question.question.blankdetail.describe
        except:
            return ""

    def get_question_id(self, obj):
        try:
            return obj.question.question.id
        except:
            return None


class PaperSerializer(serializers.ModelSerializer):

    paper_name = serializers.CharField(source='exam.exam_name')
    exam_id = serializers.CharField(source='exam.id')
    start_time = serializers.DateTimeField(format="%Y-%m-%d %H:%M:%S", source="create_time")
    duration = serializers.IntegerField(source='exam.duration')
    username = serializers.CharField(source='student.user.real_name')
    studentid = serializers.CharField(source='student.studentID')
    question_total = serializers.IntegerField(source='exam.question_total')
    paper_status = serializers.SerializerMethodField()
    mc = serializers.SerializerMethodField()
    ma = serializers.SerializerMethodField()
    tf = serializers.SerializerMethodField()
    bl = serializers.SerializerMethodField()
    sa = serializers.SerializerMethodField()

    class Meta:
        model = Paper
        fields = ['id', 'paper_name', 'exam_id', 'username', 'studentid', 'start_time', 'duration', 'score', 'comment', 'question_total', 'status', 'paper_status', 'mc', 'ma', 'tf', 'bl', 'sa']

    def get_paper_status(self, obj):
        return "已评分" if obj.score is not None else "未评分"

    def get_mc(self, obj):
        pq = PaperQuestion.objects.filter(paper__id=obj.id, question__question__question_type='MC').order_by('question__order')
        return PaperChoiceQuestionDetailSerializer(pq, many=True).data

    def get_ma(self, obj):
        pq = PaperQuestion.objects.filter(paper__id=obj.id, question__question__question_type='MA').order_by('question__order')
        return PaperChoiceQuestionDetailSerializer(pq, many=True).data

    def get_tf(self, obj):
        pq = PaperQuestion.objects.filter(paper__id=obj.id, question__question__question_type='TF').order_by('question__order')
        return PaperChoiceQuestionDetailSerializer(pq, many=True).data

    def get_bl(self, obj):
        pq = PaperQuestion.objects.filter(paper__id=obj.id, question__question__question_type='BL').order_by('question__order')
        return PaperBlankQuestionDetailSerializer(pq, many=True).data

    def get_sa(self, obj):
        pq = PaperQuestion.objects.filter(paper__id=obj.id, question__question__question_type='SA').order_by('question__order')
        return PaperBlankQuestionDetailSerializer(pq, many=True).data

class PaperUpdateSerializer(serializers.ModelSerializer):

    class Meta:
        model = Paper
        fields = ['score']

class PaperQuestionUpdateSerializer(serializers.ModelSerializer):

    class Meta:
        model = PaperQuestion
        fields = ['correctscore']
    
    def update(self, instance, validated_data):
        with transaction.atomic():
            super().update(instance, validated_data)
            paper_score = 0
            for pq in PaperQuestion.objects.filter(paper=instance.paper):
                paper_score = paper_score + pq.correctscore
            instance.paper.score = paper_score
            instance.paper.save()
        return instance

class CourseListSerializer(serializers.HyperlinkedModelSerializer):
    avatar_url = serializers.SerializerMethodField()
    course_id = serializers.CharField(source='id')
    teacher_set = TeacherNameSerializer(many=True, read_only=True)
    student_count = serializers.SerializerMethodField()
    create_time = serializers.DateTimeField(format="%Y-%m-%d %H:%M:%S")
    # status = FormatTransField(transname='class_status')
    course_type = FormatTransField(transname='course_type')
    score = serializers.SerializerMethodField()
    comment = serializers.SerializerMethodField()
    
    class Meta:
        model = Course
        fields = ['course_id', 'avatar_id', 'course_name', 'teacher_set', 'student_count', 'create_time', 'status', 'course_type', 'theo_hours', 'prac_hours', 'credit', 'score', 'comment', 'capacity', 'choice_code', 'avatar_url', 'describe', 'price', 'editor']

    def get_student_count(self, obj):
        return obj.student_set.count()
    
    def get_avatar_url(self, obj):
        return settings.MEDIA_HOST + obj.avatar.location.url

    def get_score(self, obj):
        # todo 因多端共用接口，未做身份区分导致的报错： ability.models.UserProfile.student.RelatedObjectDoesNotExist: UserProfile has no student
        return 0
        score = StudentCourse.objects.get(student=self.context['request'].user.student, course=obj).score
        return score

    def get_comment(self, obj):
        return ''
        comment = StudentCourse.objects.get(student=self.context['request'].user.student, course=obj).comment
        return comment

class StuCourseListSerializer(CourseListSerializer):
    choiced = serializers.SerializerMethodField()

    class Meta:
        model = Course
        fields = ['course_id', 'course_name', 'avatar_id', 'teacher_set', 'student_count', 'create_time', 'status', 'course_type', 'theo_hours', 'prac_hours', 'credit', 'score', 'comment', 'capacity', 'choice_code', 'avatar_url', 'describe', 'choiced']

    def get_choiced(self, obj):
        try:
            return Student.choicedCourse(self.context['request'].user.student, obj.id)
        except Exception as e:
            return 0

class OpenCourseListSerializer(serializers.HyperlinkedModelSerializer):
    course_id = serializers.CharField(source='id')
    teacher_set = TeacherNameSerializer(many=True, read_only=True)
    student_count = serializers.SerializerMethodField()
    create_time = serializers.DateTimeField(format="%Y-%m-%d %H:%M:%S")
    status = FormatTransField(transname='class_status')
    course_type = FormatTransField(transname='course_type')
    score = serializers.SerializerMethodField()
    choiced = serializers.SerializerMethodField()
    need_choice_code = serializers.SerializerMethodField()
    
    class Meta:
        model = Course
        fields = ['course_id', 'course_name', 'teacher_set', 'student_count', 'create_time', 'status', 'course_type', 'theo_hours', 'prac_hours', 'credit', 'score', 'choiced', 'need_choice_code', 'capacity']

    def get_need_choice_code(self, obj):
        return len(obj.choice_code) == 4

    def get_student_count(self, obj):
        return obj.student_set.count()

    def get_score(self, obj):
        # todo 因多端共用接口，未做身份区分导致的报错： ability.models.UserProfile.student.RelatedObjectDoesNotExist: UserProfile has no student
        return 0
        score = StudentCourse.objects.get(student=self.context['request'].user.student, course=obj).score
        return score

    def get_choiced(self, obj):
        try:
            return Student.choicedCourse(self.context['request'].user.student, obj.id)
        except Exception as e:
            return 0

class StuCourseSerializer(serializers.ModelSerializer):
    course_id = serializers.CharField(source='id')
    course_type = FormatTransField(transname='course_type', read_only=True)
    teacher_set = TeacherNameSerializer(many=True, read_only=True)
    course_status = FormatTransField(source='status', transname='class_status', read_only=True)
    score = serializers.SerializerMethodField()
    comment = serializers.SerializerMethodField()
    # chapters = ChapterListSerializer(source='chapter_set', many=True)

    class Meta:
        model = Course
        fields = ['course_id', 'course_name', 'teacher_set', 'describe', 'course_status', 'score', 'comment', 'course_type', 'theo_hours', 'prac_hours', 'credit', 'editor']

    def get_score(self, obj):
        score = StudentCourse.objects.get(student=self.context['request'].user.student, course=obj).score
        return score

    def get_comment(self, obj):
        comment = StudentCourse.objects.get(student=self.context['request'].user.student, course=obj).comment
        return comment

class StuChapterSerializer(serializers.HyperlinkedModelSerializer):
    detail = serializers.CharField(required=False)
    detail_type = serializers.CharField(required=False)
    chapter_name = serializers.CharField(required=False)
    parent_name = serializers.CharField(source='parent.chapter_name', read_only=True, default=None)

    class Meta:
        model = Chapter
        fields = ('id', 'chapter_name', 'detail', 'detail_type', 'parent_name')

class StuExperimentListSerializer(serializers.HyperlinkedModelSerializer):
    knowledges = serializers.SerializerMethodField()
    score = serializers.SerializerMethodField()
    report = serializers.SerializerMethodField()
    
    class Meta:
        model = Experiment
        fields = ['id', 'experiment_name', 'knowledges', 'duration', 'score', 'report']

    def get_knowledges(self, obj):
        knowledges = obj.knowledge.all()
        res = ""
        for knowledge in knowledges:
            res += "、" + knowledge.knowledge_name if res != "" else knowledge.knowledge_name
        return res

    # def get_course_name(self, obj):
    #     courses = obj.course.all()
    #     res = ""
    #     for course in courses:
    #         if StudentCourse.objects.filter(student=self.context['request'].user.student, course=course, status='N').count()>0:
    #             res += "、" + course.course_name if res != "" else course.course_name
    #     return res

    def get_score(self, obj):
        return 0
        # score = Report.objects.filter(experiment=obj,student=self.context['request'].user.student).aggregate(Avg("score"))
        # return score

    def get_report(self, obj):
        try:
            report = Report.objects.all().filter(experiment=obj,student=self.context['request'].user.student)
            return ReportListSerializer(report, many=True).data
        except:
            return []

class StuReportSerializer(serializers.ModelSerializer):

    experiment_name = serializers.CharField(source='experiment.experiment_name')
    report_title = serializers.CharField(source='title')
    submit_time = serializers.DateTimeField(format="%Y-%m-%d %H:%M:%S")
    studentid = serializers.CharField(source='student.studentID')
    username = serializers.CharField(source='student.user.real_name')
    attach = AttachSerializer(many=True, read_only=True, source='attach_set')
    knowledges = serializers.SerializerMethodField()

    class Meta:
        model = Report
        fields = ['id', 'report_title', 'experiment_name', 'studentid', 'username', 'submit_time', 'knowledges', 'score', 'comment', 'content', 'attach']

    def get_access_log(self, obj):
        try:
            student = obj.student
            environment = obj.experiment.environment
            instance = Instance.objects.get(student=student, environment=environment)
            accesslogs = AccessLog.objects.filter(instance=instance)
            return AccessLogSerializer(accesslogs, many=True).data
        except:
            return None

    def get_operate_log(self, obj):
        try:
            student = obj.student
            environment = obj.experiment.environment
            instance = Instance.objects.get(student=student, environment=environment)
            operatelogs = OperateLog.objects.filter(instance=instance)
            return OperateLogSerializer(operatelogs, many=True).data
        except:
            return None

    def get_knowledges(self, obj):
        knowledges = obj.experiment.knowledge.all()
        res = ""
        for knowledge in knowledges:
            res += "、" + knowledge.knowledge_name if res != "" else knowledge.knowledge_name
        return res

class StuExperimentSerializer(serializers.ModelSerializer):
    environment_id = serializers.SerializerMethodField()
    knowledges = serializers.SerializerMethodField()
    # ending_time = serializers.DateTimeField(format="%Y-%m-%d %H:%M:%S")
    knowledges_path = serializers.SerializerMethodField()
    # experiment_name = serializers.CharField(source='experiment_name')
    environment = EnvironmentSerializer()
    instance = serializers.SerializerMethodField()
    user_count = serializers.SerializerMethodField()
    course_names = serializers.SerializerMethodField()
    teacher_names = serializers.SerializerMethodField()
    title_list = serializers.SerializerMethodField()

    class Meta:
        model = Experiment
        fields = ['id', 'experiment_name', 'detail_type', 'duration', 'title_list','vnccode', 'describe', 'knowledges', 'knowledges_path', 'environment_id', 'environment', 'instance', 'type', 'price', 'user_limit', 'user_count', 'intro', 'course_names', 'teacher_names']
    
    def get_knowledges(self, obj):
        knowledges = obj.knowledge.all()
        res = ""
        for knowledge in knowledges:
            res += "、" + knowledge.knowledge_name if res != "" else knowledge.knowledge_name
        return res

    def get_environment_id(self, obj):
        environment = obj.environment
        return environment.id if environment is not None else None

    def get_knowledges_path(self, obj):
        knowledges = obj.knowledge.all()
        res = ""
        for knowledge in knowledges:
            res_path = knowledge.knowledge_name
            temp = knowledge.parent
            while temp!= None:
                res_path = temp.knowledge_name + '/' + res_path
                temp = temp.parent
            res += "、" + res_path
        return res[1:]

    def get_course_names(self, obj):
        res = ''
        for c in obj.course.all():
            res += '、' + c.course_name
        return res[1:]

    def get_teacher_names(self, obj):
        res = ''
        for c in obj.teacher.all():
            res += '、' + c.user.real_name
        return res[1:]

    def get_user_count(self, obj):
        return obj.student.count()

    def get_choiced(self, obj):
        try:
            return Student.choicedCourse(self.context['student'], obj.id)
        except Exception as e:
            return 0

    def get_instance(self, obj):
        instances = []
        # ci = CloudInstance()
        if obj.environment is None:
            return []
        images = obj.environment.image.all()
        new_images = []
        cii = None
        if obj.experiment_type == "double" and len(images) == 2:
            for image in images:
                if int(image.id) == int(obj.primary_image_id):
                    new_images.append(image)
                else:
                    cii = image
            new_images.append(cii)
        else:
            if len(images) == 0:
                new_images = ''
            elif obj.experiment_type == "double":
                new_images = [images[0],images[0]]
            else:
                new_images = [images[0]]
        for image in new_images:
            data = {}
            data['ImageId'] = image.imageId
            data['ImageName'] = image.image_name
            data['OsName'] = image.opration_system
            data['Arc'] = image.architecture
            data['PrivateIpAddresses'] = ''
            data['PublicIpAddresses'] = ''
            ins = Instance.objects.filter(environment=obj.environment, student=self.context['student'], status='N',image=image).first()
            print('instance of env-{} stu-{}'.format(obj.environment.id, self.context['student'].id))
            if ins is None:
                data['Name'] = ''
                data['Status'] = 'UNCREATED'
                data['InsId'] = ''
                data['StatusLabel'] = instStatus[data['Status']]
                instances.append(data)
                continue
            # InstanceStatus = ci.DescribeInstance(ins.instanceId)
            # if InstanceStatus is None:
            #     data['Name'] = ''
            #     data['Status'] = 'UNCREATED'
            #     data['StatusLabel'] = instStatus[data['Status']]
            #     data['InsId'] = ''
            #     instances.append(data)
            #     ins.status = 'C'
            #     ins.save()
            #     continue
            data['Name'] = ins.name
            # data['Status'] = InstanceStatus.InstanceState
            print(ins.instanceId)
            current_status = proxmox.status_vm(ins.instanceId)
            print(current_status)
            print("======================")
            # status = current_status.get('status')
            # data['Status'] = 'RUNNING' if hasattr(current_status, 'status') and status == 'running'  else 'STOPPED'
            data['Status'] = 'RUNNING'
            data['StatusLabel'] = instStatus[data['Status']]
            data['InsId'] = ins.instanceId
            # if InstanceStatus.PrivateIpAddresses != None:
            #     # data['PrivateIpAddresses'] = InstanceStatus.PrivateIpAddresses[0]
            #     ins.private_ip_address = InstanceStatus.PrivateIpAddresses[0]
            #     ins.private_ip_address = InstanceStatus.PrivateIpAddresses[0]
            data['PublicIpAddresses'] = '10.56.5.143'
            ins.ip_address = '10.56.5.143'
            ins.save()
            # if InstanceStatus.PublicIpAddresses != None:
            #     data['PublicIpAddresses'] = InstanceStatus.PublicIpAddresses[0]
            #     ins.ip_address = InstanceStatus.PublicIpAddresses[0]
            #     ins.save()
            # if data['Status'] == 'RUNNING':
                #data['vnc_url'] = ci.DescribeInstanceVncUrl(data['InsId'])
            data['port'] = 556
            instances.append(data)
        return instances
    def get_title_list(self, obj):
        describe_list = ExperimentChapter.objects.filter(experiment_id=obj.id).values('id', 'detail')
        aa = []
        for u in describe_list:
            detail = markdown.markdown(u['detail'], extensions=['markdown.extensions.fenced_code']).strip()
            title_flag = '</p>'
            if detail.find("<h1>") == 0:
                title_flag = "</h1>"
            if detail.find("<h3>") == 0:
                title_flag = "</h3>"
            if detail.find("<h2>") == 0:
                title_flag = "</h2>"
            aa.append({

                "title": detail[len(f"{title_flag}") - 1:detail.find(f"{title_flag}"):1]
            })
        return aa
            
class StuExperimentChapterSerializer(serializers.ModelSerializer):

    pages = serializers.SerializerMethodField()
    current_page = serializers.SerializerMethodField()
    title_list = serializers.SerializerMethodField()
    class Meta:
        model = ExperimentChapter
        fields = ['detail','pages','current_page','title_list']

    def get_pages(self, obj):
        return ExperimentChapter.objects.filter(experiment_id=obj.experiment_id).count()

    def get_current_page(self, obj):
        ids = ExperimentChapter.objects.filter(experiment_id=obj.experiment_id).order_by("id").values("id")
        for id in ids:
            if id == obj.id:
                return ids.index(id)
        return 0

    def get_title_list(self, obj):
        describe_list = ExperimentChapter.objects.filter(experiment_id=obj.experiment_id).values('id', 'detail')
        aa = []
        for u in describe_list:
            detail = markdown.markdown(u['detail'], extensions=['markdown.extensions.fenced_code']).strip()
            title_flag = '</p>'
            if detail.find("<h1>") == 0:
                title_flag = "</h1>"
            if detail.find("<h3>") == 0:
                title_flag = "</h3>"
            if detail.find("<h2>") == 0:
                title_flag = "</h2>"
            aa.append({

                "title": detail[len(f"{title_flag}") - 1:detail.find(f"{title_flag}"):1]
            })
        return aa

class StuExamListSerializer(serializers.ModelSerializer):

    exam_name = serializers.CharField()
    course_name = serializers.CharField(source='course.course_name')
    start_time = serializers.DateTimeField(format="%Y-%m-%d %H:%M:%S")
    duration = serializers.IntegerField()
    question_total = serializers.IntegerField()
    exam_status = serializers.SerializerMethodField()
    score = serializers.SerializerMethodField()

    class Meta:
        model = Exam
        fields = ['id', 'exam_name', 'course_name', 'start_time', 'duration', 'question_total', 'exam_status', 'score']

    def get_exam_status(self, obj):
        # pst = pytz.timezone('America/Los_Angeles')
        time_diff = datetime.utcnow() - obj.start_time.replace(tzinfo=None)
        time_delta = time_diff.total_seconds() // 60
        print('now:{}, start:{}, diff{}, delta:{}'.format(datetime.now(), obj.start_time.replace(tzinfo=None), time_diff, time_delta))
        if time_delta < 0:
            return 0
        if time_delta > (obj.duration * 8):
            return 2
        else:
            return 1

    def get_score(self, obj):
        try:
            score = Paper.objects.get(student=self.context['request'].user.student, exam=obj).score
            return score
        except:
            return None

class StuPaperCreateSerializer(serializers.ModelSerializer):
    
    class Meta:
        model = Paper
        fields = ['id']

class StuExamSerializer(serializers.HyperlinkedModelSerializer, StudentCountMixin):
    start_time = serializers.DateTimeField(format="%Y-%m-%d %H:%M:%S")
    teacher_name = serializers.SerializerMethodField()
    paper_id = serializers.SerializerMethodField()
    paper_status = serializers.SerializerMethodField()
    mc = serializers.SerializerMethodField()
    ma = serializers.SerializerMethodField()
    tf = serializers.SerializerMethodField()
    bl = serializers.SerializerMethodField()
    sa = serializers.SerializerMethodField()
    course = CourseSerializer()
    student_count = serializers.SerializerMethodField()

    class Meta:
        model = Exam
        fields = ['id', 'start_time', 'duration', 'exam_name', 'exam_describe', 'question_total', 'teacher_name', 'paper_id', 'paper_status', 'mc' ,'ma', 'tf', 'bl', 'sa', 'course', 'student_count']

    def get_paper_id(self, obj):
        try:
            paper_id = Paper.objects.filter(student=self.context['request'].user.student, exam=obj).order_by('-id')[0].id
            return paper_id
        except:
            return None

    def get_paper_status(self, obj):
        try:
            paper_status = Paper.objects.filter(student=self.context['request'].user.student, exam=obj).order_by('-id')[0].status
            return paper_status
        except:
            return None

    def get_mc(self, obj):
        eq = ExamQuestion.objects.filter(exam__id=obj.id, question_type='MC').order_by('order')
        return ChoiceQuestionDetailSerializer(eq, many=True).data

    def get_ma(self, obj):
        eq = ExamQuestion.objects.filter(exam__id=obj.id, question_type='MA').order_by('order')
        return ChoiceQuestionDetailSerializer(eq, many=True).data

    def get_tf(self, obj):
        eq = ExamQuestion.objects.filter(exam__id=obj.id, question_type='TF').order_by('order')
        return ChoiceQuestionDetailSerializer(eq, many=True).data

    def get_bl(self, obj):
        eq = ExamQuestion.objects.filter(exam__id=obj.id, question_type='BL').order_by('order')
        return BlankQuestionDetailSerializer(eq, many=True).data

    def get_sa(self, obj):
        eq = ExamQuestion.objects.filter(exam__id=obj.id, question_type='SA').order_by('order')
        return BlankQuestionDetailSerializer(eq, many=True).data
    
    def get_teacher_name(self, obj):
        try:
            return obj.teacher.user.real_name
        except:
            return ''

class StuReportCreateSerializer(serializers.ModelSerializer):

    class Meta:
        model = Report
        fields = ['id']
